package com.ztgf.shopping.service.shop;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.ztgf.common.utils.CustomizeUtil;
import com.ztgf.shopping.common.config.YmlConfig;
import com.ztgf.shopping.mapper.shop.ShopOnlineMapper;
import com.ztgf.shopping.models.bo.shop.ShopOnlineQueryBO;
import com.ztgf.shopping.models.dto.shop.ShopOnlineDTO;
import com.ztgf.shopping.models.service.shop.IShopOnlineService;
import com.ztgf.shopping.models.vo.shop.ShopImResponseVO;
import com.ztgf.shopping.models.vo.shop.ShopOnlineQueryListVO;
import com.ztgf.shopping.models.vo.shop.ShopOnlineVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@DubboService
public class ShopOnlineServiceImpl extends ServiceImpl<ShopOnlineMapper, ShopOnlineDTO> implements IShopOnlineService {

    @Resource
    private YmlConfig ymlConfig;
    @Value("${im.url}")
    private String imUrl;

    @Async
    @Override
    public void addOnShopId(Long shopId) {
        try {
            // 当天开始时间
            String startTime = CustomizeUtil.getStartTime();
            // 当天结束时间
            String endTime = CustomizeUtil.getEndTime();
            // 获取最近的一条登录信息
            Wrapper<ShopOnlineDTO> wrapperA = new EntityWrapper<>();
            wrapperA.eq("shop_id", shopId);
            wrapperA.ge("create_time", startTime);
            wrapperA.le("create_time", endTime);
            wrapperA.orderBy("create_time", false);
            ShopOnlineDTO selectOne = this.selectOne(wrapperA);
            if (selectOne != null && selectOne.getOutTime() == null) {
                Date nowDate = new Date();
                long start = selectOne.getCreateTime().getTime();
                long end = nowDate.getTime();
                long min = (end - start) / (1000 * 60);
                ShopOnlineDTO updateDto = new ShopOnlineDTO();
                updateDto.setOutTime(nowDate);
                updateDto.setId(selectOne.getId());
                updateDto.setDuration(min);
                updateDto.setIsOnline(0);
                this.updateById(updateDto);
            }
            ShopOnlineDTO insertDto = new ShopOnlineDTO();
            insertDto.setShopId(shopId);
            insertDto.setId(ymlConfig.getPkId());
            insertDto.setIsOnline(1);
            this.insert(insertDto);
        } catch (Exception e) {
            log.info("添加店铺在线时长表失败");
            e.printStackTrace();
        }
    }

    @Override
    public List<ShopOnlineDTO> queryDayNotOutList(Long lastNo) {
        // 页码
        Page<ShopOnlineDTO> page = new Page<>(0, 50);
        // 构建查询
        Wrapper<ShopOnlineDTO> wrapper = new EntityWrapper<>();
        wrapper.eq("is_online", 1);
        wrapper.gt("id", lastNo);
        wrapper.orderBy("shop_id", false);
        Page<ShopOnlineDTO> selectPage = this.selectPage(page, wrapper);
        return selectPage.getRecords();
    }

    @Async
    @Override
    public void updateShopOutTime(Long shopId) {
        try {
            // 当天开始时间
            String startTime = CustomizeUtil.getStartTime();
            // 当天结束时间
            String endTime = CustomizeUtil.getEndTime();
            // 获取最近的一条登录信息
            Wrapper<ShopOnlineDTO> wrapperA = new EntityWrapper<>();
            wrapperA.eq("shop_id", shopId);
            wrapperA.ge("create_time", startTime);
            wrapperA.le("create_time", endTime);
            wrapperA.orderBy("create_time", false);
            ShopOnlineDTO selectOne = this.selectOne(wrapperA);
            if (selectOne != null && selectOne.getOutTime() == null) {
                Date nowDate = new Date();
                long start = selectOne.getCreateTime().getTime();
                long end = nowDate.getTime();
                long min = (end - start) / (1000 * 60);
                ShopOnlineDTO updateDto = new ShopOnlineDTO();
                updateDto.setOutTime(nowDate);
                updateDto.setId(selectOne.getId());
                updateDto.setDuration(min);
                updateDto.setIsOnline(0);
                updateDto.setUpdateTime(new Date());
                this.updateById(updateDto);
            }
        } catch (Exception e) {
            log.info("修改用户退出登录时间失败");
            e.printStackTrace();
        }
    }

    @Override
    public Page<ShopOnlineQueryListVO> queryPageList(ShopOnlineQueryBO bo) {
        Page<ShopOnlineQueryListVO> page = new Page<>(bo.getPageNo(), bo.getPageSize());
        List<ShopOnlineQueryListVO> list = baseMapper.queryPageList(page, bo);
        if (CustomizeUtil.listIsNotNull(list)) {
            for (ShopOnlineQueryListVO vo : list) {
                // 获取最近的一条登录信息
                Wrapper<ShopOnlineDTO> wrapperA = new EntityWrapper<>();
                wrapperA.eq("shop_id", vo.getShopId());
                wrapperA.orderBy("create_time", false);
                ShopOnlineDTO selectOne = this.selectOne(wrapperA);
                // 处理最近一次登录和退出时间
                if (selectOne != null) {
                    vo.setLatelySignTime(selectOne.getCreateTime());
                    if (selectOne.getOutTime() != null) {
                        vo.setLatelyOutTime(selectOne.getOutTime());
                    }
                    // 在线状态
                    vo.setIsOnline(selectOne.getIsOnline());
                }
                // 处理最后在线时长
                if (CustomizeUtil.strIsNotNull(bo.getStartTimeA()) && CustomizeUtil.strIsNotNull(bo.getEndTimeA())) {
                    // 获取店铺自定义时间在线时长
                    Long autoOnlineTime = baseMapper.getShopAutoOnlineTime(vo.getShopId(), bo.getStartTimeA(), bo.getEndTimeA());
                    String dateFormat = CustomizeUtil.getOtherDateFormat(autoOnlineTime);
                    vo.setOnLineTime(dateFormat);
                } else {
                    String otherDateFormat = CustomizeUtil.getOtherDateFormat(vo.getOnLines());
                    vo.setOnLineTime(otherDateFormat);
                }
                // 处理回复率
                String responseRate = this.getResponseRate(vo.getShopId(), bo);
                vo.setResponseRate(responseRate);
                String fiveResponseRate = this.getFiveResponseRate(vo.getShopId(), bo);
                vo.setFiveResponseRate(fiveResponseRate);
                String tenResponseRate = this.getTenResponseRate(vo.getShopId(), bo);
                vo.setTenResponseRate(tenResponseRate);
                String threeResponseRate = this.getThreeResponseRate(vo.getShopId(), bo);
                vo.setHalfHourResponseRate(threeResponseRate);
            }
        }
        page.setRecords(list);
        return page;
    }

    @Override
    public ShopImResponseVO getShopImState(Long shopId) {
        ShopImResponseVO errorResponse = new ShopImResponseVO();
        try {
            // 查询店铺IMId
            Long shopImId = baseMapper.getShopImId(shopId);
            // im项目接口请求
            RestTemplate restTemplate = new RestTemplate();
            ResponseEntity<String> responseEntity = restTemplate.getForEntity(imUrl, String.class, shopImId.toString());
            // 接口响应码
            int responseValue = responseEntity.getStatusCode().value();
            log.info("im接口响应码:{}", responseValue);
            // 响应body
            String responseEntityBody = responseEntity.getBody();
            log.info("im接口响应内容:{}", responseEntityBody);
            ShopImResponseVO responseVO = JSONObject.parseObject(responseEntityBody, ShopImResponseVO.class);
            if (responseVO != null) {
                responseVO.setResponseValue(responseValue);
                return responseVO;
            }
            errorResponse.setResponseValue(1);
            return errorResponse;
        } catch (Exception e) {
            errorResponse.setMsg("im接口请求报错");
            errorResponse.setCode(1);
            errorResponse.setShopId(shopId);
            errorResponse.setStatus("false");
            errorResponse.setResponseValue(1);
            log.info("im接口请求报错信息:{}", e.getMessage());
            e.printStackTrace();
        }
        return errorResponse;
    }

    /**
     * @return : java.lang.String
     * @Author :chenyu.wang
     * @Description : 获取店铺回复率
     * @Date : 11:58 2021.01.13
     * @Param : [shopId, bo]
     **/
    private String getResponseRate(Long shopId, ShopOnlineQueryBO bo) {
        try {
            // 获取咨询人数
            Integer consultNum = baseMapper.getConsultNum(bo, shopId);
            // 获取回复次数
            Integer replyNum = baseMapper.getReplyNum(bo, shopId);
            // 咨询人数
            BigDecimal numA = new BigDecimal(consultNum);
            // 回复次数
            BigDecimal numB = new BigDecimal(replyNum);
            // 回复率=回复人数/咨询人数。
            String responseRateA = CustomizeUtil.ADivideBPercent(numB, numA);
            log.info("正常回复率:{}", responseRateA);
            if (CustomizeUtil.strIsNotNull(bo.getStartTime()) && CustomizeUtil.strIsNotNull(bo.getEndTime())) {
                // 时间不为空则要计算平均值
                BigDecimal divide = numB.divide(numA);
                BigDecimal newDivide = divide.setScale(BigDecimal.ROUND_UP, 2);
                // 获取时间间隔天数
                int timeDay = CustomizeUtil.getTimeDay(bo.getStartTime(), bo.getEndTime());
                BigDecimal day = new BigDecimal(timeDay);
                String responseRateB = CustomizeUtil.ADivideBPercent(newDivide, day);
                log.info("平均回复率:{}", responseRateB);
                return responseRateB;
            } else {
                return responseRateA;
            }
        } catch (Exception e) {
            log.info("获取回复率报错信息:{}", e.getMessage());
            e.printStackTrace();
        }
        return "0.00%";
    }

    /**
     * @return : java.lang.String
     * @Author :chenyu.wang
     * @Description : 获取店铺五分钟回复率
     * @Date : 10:04 2021.01.18
     * @Param : [shopId, bo]
     **/
    private String getFiveResponseRate(Long shopId, ShopOnlineQueryBO bo) {
        try {
            // 获取咨询人数
            Integer consultNum = baseMapper.getConsultNum(bo, shopId);
            // 获取店铺咨询人列表
            List<ShopOnlineVO> consultList = baseMapper.getConsultList(bo, shopId);
            if (consultNum.equals(0) && CustomizeUtil.listIsNull(consultList)) {
                return "-";
            }
            // 五分钟
            List<Long> list = new ArrayList<>();
            for (ShopOnlineVO onlineVO : consultList) {
                // 获取回复时间
                ShopOnlineVO replyTime = baseMapper.getReplyTime(bo, shopId, onlineVO.getShopId());
                if (replyTime != null) {
                    // 是否在五分钟内
                    boolean checkFive = CustomizeUtil.checkTwoTime(onlineVO.getCreateTime(), replyTime.getCreateTime(), 5);
                    if (checkFive) {
                        list.add(replyTime.getShopId());
                    }
                }
            }
            int size = list.size();
            // 咨询人数
            BigDecimal numA = new BigDecimal(consultNum);
            // 回复次数
            BigDecimal numB = new BigDecimal(size);
            String responseRateA = CustomizeUtil.ADivideBPercent(numB, numA);
            log.info("五分钟回复率为:{}", responseRateA);
            return responseRateA;
        } catch (Exception e) {
            log.info("获取店铺五分钟回复率失败:{}", e.getMessage());
            e.printStackTrace();
        }
        return "0.00%";
    }

    /**
     * @return : java.lang.String
     * @Author :chenyu.wang
     * @Description : 获取用户十分钟回复率
     * @Date : 10:23 2021.01.18
     * @Param : [shopId, bo]
     **/
    private String getTenResponseRate(Long shopId, ShopOnlineQueryBO bo) {
        try {
            // 获取咨询人数
            Integer consultNum = baseMapper.getConsultNum(bo, shopId);
            // 获取店铺咨询人列表
            List<ShopOnlineVO> consultList = baseMapper.getConsultList(bo, shopId);
            if (consultNum.equals(0) && CustomizeUtil.listIsNull(consultList)) {
                return "-";
            }
            // 十分钟
            List<Long> listA = new ArrayList<>();
            for (ShopOnlineVO onlineVO : consultList) {
                // 获取回复时间
                ShopOnlineVO replyTime = baseMapper.getReplyTime(bo, shopId, onlineVO.getShopId());
                if (replyTime != null) {
                    // 是否在十分钟内
                    boolean checkTen = CustomizeUtil.checkTwoTime(onlineVO.getCreateTime(), replyTime.getCreateTime(), 10);
                    if (checkTen) {
                        listA.add(replyTime.getShopId());
                    }
                }
            }
            int size = listA.size();
            // 咨询人数
            BigDecimal numA = new BigDecimal(consultNum);
            // 回复次数
            BigDecimal numB = new BigDecimal(size);
            String responseRateA = CustomizeUtil.ADivideBPercent(numB, numA);
            log.info("十分钟回复率为:{}", responseRateA);
            return responseRateA;
        } catch (Exception e) {
            log.info("获取店铺十分钟回复率失败:{}", e.getMessage());
            e.printStackTrace();
        }
        return "0.00%";
    }

    /**
     * @return : java.lang.String
     * @Author :chenyu.wang
     * @Description : 获取店铺半小时回复率
     * @Date : 10:23 2021.01.18
     * @Param : [shopId, bo]
     **/
    private String getThreeResponseRate(Long shopId, ShopOnlineQueryBO bo) {
        try {
            // 获取咨询人数
            Integer consultNum = baseMapper.getConsultNum(bo, shopId);
            // 获取店铺咨询人列表
            List<ShopOnlineVO> consultList = baseMapper.getConsultList(bo, shopId);
            if (consultNum.equals(0) && CustomizeUtil.listIsNull(consultList)) {
                return "-";
            }
            // 半小时
            List<Long> listC = new ArrayList<>();
            for (ShopOnlineVO onlineVO : consultList) {
                // 获取回复时间
                ShopOnlineVO replyTime = baseMapper.getReplyTime(bo, shopId, onlineVO.getShopId());
                if (replyTime != null) {
                    // 是否在三十分钟内
                    boolean checkThree = CustomizeUtil.checkTwoTime(onlineVO.getCreateTime(), replyTime.getCreateTime(), 30);
                    if (checkThree) {
                        listC.add(replyTime.getShopId());
                    }
                }
            }
            int size = listC.size();
            // 咨询人数
            BigDecimal numA = new BigDecimal(consultNum);
            // 回复次数
            BigDecimal numB = new BigDecimal(size);
            String responseRateA = CustomizeUtil.ADivideBPercent(numB, numA);
            log.info("半小时回复率为:{}", responseRateA);
            return responseRateA;
        } catch (Exception e) {
            log.info("获取店铺半小时回复率失败:{}", e.getMessage());
            e.printStackTrace();
        }
        return "0.00%";
    }

}
